package com.badou.project.rest.service.impl;


import com.alibaba.fastjson.JSONObject;
import com.badou.api.intermanage.interfacedetail.model.InterFaceDetailEntity;
import com.badou.api.intermanage.interfacedetail.service.IInterFaceDetailService;
import com.badou.api.intermanage.interfacelogger.model.InterFaceLoggerEntity;
import com.badou.api.intermanage.interfacelogger.service.IInterFaceLoggerService;
import com.badou.api.intermanage.interfacepermission.model.InterFacePermissionEntity;
import com.badou.api.intermanage.interfacepermission.service.IInterFacePermissionService;
import com.badou.api.intermanage.netinformation.model.NetInformationEntity;
import com.badou.api.intermanage.netinformation.service.INetInformationService;
import com.badou.brms.dictionary.DictionaryLib;
import com.badou.core.base.local.LogonCertificate;
import com.badou.core.base.local.LogonCertificateHolder;
import com.badou.core.base.query.QueryCriterion;
import com.badou.core.base.query.QueryOperSymbolEnum;
import com.badou.core.base.query.support.QueryHibernatePlaceholderParam;
import com.badou.designer.jdbc.common.util.DataBeanSelector;
import com.badou.designer.jdbc.common.util.DataSelector;
import com.badou.designer.jdbc.common.web.form.BaseCommonSaveForm;
import com.badou.designer.jdbc.core.service.impl.BaseModuleService;
import com.badou.designer.jdbc.core.util.UUIDUtils;
import com.badou.designer.jdbc.core.vo.BaseVO;
import com.badou.designer.jdbc.core.vo.FieldVO;
import com.badou.designer.jdbc.core.vo.SimpleVO;
import com.badou.designer.module.database.dao.IModuleDatabaseDao;
import com.badou.designer.module.design.ModuleCacheContainer;
import com.badou.designer.module.design.ModuleConstants;
import com.badou.designer.module.design.base.IModuleEntity;
import com.badou.designer.module.design.model.MdFieldEntity;
import com.badou.designer.module.design.model.MdModuleEntity;
import com.badou.designer.module.design.model.MdModuleLinkEntity;
import com.badou.project.rest.StatusEnum;
import com.badou.project.rest.dao.IBaseRestDAO;
import com.badou.project.rest.service.IBaseRestService;
import com.badou.security.ssl.token.pojo.Token;
import com.badou.security.ssl.token.service.ITokenService;
import com.badou.tools.common.file.jxlexcel.ExcelImportException;
import org.apache.commons.httpclient.util.DateParseException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;


@Service
public class BaseRestService extends BaseModuleService implements IBaseRestService {
	
	@Autowired
	private IBaseRestDAO baseRestDAO;
	@Autowired
	private ITokenService tokenService;
	@Autowired
	private IInterFaceDetailService interFaceDetailService;
	@Autowired
	private INetInformationService netInformationService;
	@Autowired 
	private IInterFacePermissionService interFacePermissionService;
	@Autowired
	private IInterFaceLoggerService interFaceLoggerService;
	@Autowired
	private IModuleDatabaseDao moduleDatabaseDao;
	
	private static final int LOGGER_SUCCESS = 0;

	private static final int LOGGER_FAIL = 1;
	@Autowired
	public void setBaseRestDAO(IBaseRestDAO baseRestDAO) {
		this.baseRestDAO = baseRestDAO;
		setBaseDAO(baseRestDAO);
	}

	@Override
	@SuppressWarnings("unused")
	public Map<String ,Object> authPermission(Token tokenEntity,String methodName)
	{
		boolean isSuccess = false;
		Map<String,Object> result = new HashMap<String,Object>();
		String message = null;
      	String appId = tokenEntity.getAppId();
      	String appKey =tokenEntity.getAppKey();
    	LogonCertificate logon = new LogonCertificate("sa", "U00001", "超级管理员");
		LogonCertificateHolder.setLogonCertificate(logon);	
      	//返回状态
		int status=StatusEnum.OTHER_EXCEPTION.getStatus();
		int log_status=LOGGER_FAIL;
		//返回错误信息
		Throwable error = null;
		List<String> ips = null;
		String ipaddress = null;
		Boolean isIp = false;
		String interfaceName = null;
		//日志对象
		InterFaceLoggerEntity loggerEntity = new InterFaceLoggerEntity();
		//获取外网和接口对象
		QueryCriterion queryCriterion = new QueryCriterion();
//		methodName = methodName.replace(DictionaryLib.getDictionaryValue(BlockChainConsts.REST_API_PREFIX), "");
		if(methodName.indexOf("/") != -1){
			methodName = methodName.substring(0, methodName.indexOf("/"));
		}
		queryCriterion.addParam(new QueryHibernatePlaceholderParam("name", methodName, null, QueryOperSymbolEnum.eq));
		List<InterFaceDetailEntity> faceDetailEntitys =  interFaceDetailService.find(queryCriterion);
		InterFaceDetailEntity faceDetailEntity=null;
		if(faceDetailEntitys!= null && faceDetailEntitys.size()>0)
		{
			faceDetailEntity = faceDetailEntitys.get(0);
		}
		QueryCriterion queryCriterion2 = new QueryCriterion();
		queryCriterion2.addParam(new QueryHibernatePlaceholderParam("appId", appId, null, QueryOperSymbolEnum.eq));
		queryCriterion2.addParam(new QueryHibernatePlaceholderParam("appKey", appKey, null, QueryOperSymbolEnum.eq));
		List<NetInformationEntity> netInformationEntitys =  netInformationService.find(queryCriterion2);
		NetInformationEntity netInformationEntity=null;
		if(netInformationEntitys!= null && netInformationEntitys.size()>0)
		{
			netInformationEntity = netInformationEntitys.get(0);
		}
		if(netInformationEntity==null){
			//系统不存在
			status = StatusEnum.OUTTER_SYSNULL.getStatus();
			log_status = LOGGER_FAIL;
		}else if(faceDetailEntity==null){
			//接口不存在
			status = StatusEnum.OUTTER_INTERNULL.getStatus();
			log_status = LOGGER_FAIL;
		}else{
			//判断是否存在或者有权限
			QueryCriterion queryCriterion3 = new QueryCriterion();
			queryCriterion3.addParam(new QueryHibernatePlaceholderParam("interfaceId",faceDetailEntity.getId() , null, QueryOperSymbolEnum.eq));
			queryCriterion3.addParam(new QueryHibernatePlaceholderParam("netInformatId", netInformationEntity.getId() , null, QueryOperSymbolEnum.eq));
			List<InterFacePermissionEntity> entitys =  interFacePermissionService.find(queryCriterion3);
			interfaceName = faceDetailEntity.getInterfaceDetail();
			if(entitys==null||entitys.size()<=0){
				//没有权限
				status = StatusEnum.OUTTER_AUTHORITY.getStatus();
				log_status = LOGGER_FAIL;
			}else{
				if(faceDetailEntity.getStatus().intValue()!=0 && netInformationEntity.getIsCallInterface().intValue()!=0){
				 	status = StatusEnum.OUTTER_START.getStatus();
				 	log_status = LOGGER_FAIL;
				}else{
					//接口已经开启
					//接口正常
					status = StatusEnum.NORMAL.getStatus();
					log_status = LOGGER_SUCCESS;
				}
			}
		}
		//写入日志
		loggerEntity.setInterfacename(methodName);
		loggerEntity.setAppId(appId);
		loggerEntity.setAppkey(appKey);
		loggerEntity.setIsSuccess(log_status);
//		loggerEntity.setToken(tokenEntity.getToken());
		Date date = new Date();//获得系统时间.
		String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);//将时间格式转换成符合Timestamp要求的格式.
		Timestamp time1 =Timestamp.valueOf(time);//把时间转换
		loggerEntity.setRequesttime(time1);
		if(log_status==LOGGER_FAIL){
			loggerEntity.setFailreason(StatusEnum.getMessageByStatus(status).getMessage());
			interFaceLoggerService.create(loggerEntity);
		}else if(log_status==LOGGER_SUCCESS){
		//如果发生错误，直接拦截，返回错误信息
		//如果没有发生错误，不拦截
		//结束时间
		Date date2 = new Date();//获得系统时间.
		time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date2);//将时间格式转换成符合Timestamp要求的格式.
		time1 =Timestamp.valueOf(time);//把时间转换
		interFaceLoggerService.create(loggerEntity);
		isSuccess = true;
	}
		result.put("isSuccess", isSuccess);
		result.put("message", StatusEnum.getMessageByStatus(status).getMessage());
		result.put("logId", loggerEntity.getId());
		LogonCertificateHolder.clear();
		return result;
	}

	@Override
	public BaseVO saveBaseVO( MdModuleEntity moduleBean, Map<String, String> defaultFieldValue,BaseCommonSaveForm form,BaseVO baseVO ) throws Exception {
		StringBuilder error = new StringBuilder();
		String message = "";
		int type = moduleDatabaseDao.find(moduleBean.getDataSourceId()).getType();
		
		Set<MdFieldEntity> fieldsSet = new HashSet<>();
		fieldsSet.addAll(moduleBean.getFields());
		//判断关系
		for(MdModuleLinkEntity link : moduleBean.getLinkSet()){
			if (ModuleConstants.ONE_TO_ONE.equals(link.getType())) {
				MdModuleEntity mdModule = ModuleCacheContainer.getInstance().get(link.getRelatedModuleId());
				fieldsSet.addAll(mdModule.getFields());
			}
		}
		// 获取模型基类，判断是否允许更新
		IModuleEntity moduleBase =loadBaseInstance(moduleBean);
		Map<String,FieldVO> dic = new HashMap<String, FieldVO>();
		Map<String, MdFieldEntity> map = genByModuleInRest(fieldsSet,dic);
		Map<Integer, MdFieldEntity> fields = new HashMap<Integer, MdFieldEntity>();
		Map<String, Object> defaultFields = new HashMap<String, Object>();
		Map<Integer,String> displayNames = new HashMap<Integer,String>();
		StringBuffer fieldsNames = new StringBuffer();
		Map<String,String[]> details = form.getDetails();
		int i = 0;
		for(String key : details.keySet()){
			if("access_token".equals(key)||key.contains("-ori"))
				continue;
			String name = key;
			if(dic.containsKey(name)){
				if(dic.get(name).getId()!=null)
					fieldsNames.append(dic.get(name).getId().getFieldName()+",");
				if(dic.get(name).getText()!=null)
					fieldsNames.append(dic.get(name).getText().getFieldName()+",");
			}else{
				fieldsNames.append(name+",");
			}
			displayNames.put(i, key);
			i++;
		}
		//获取标题行对应字段
		fields = getDetailInRest(map, displayNames);
		//获取默认字段值
		Map<String,Object> defaultDetail = validateDefaultFieldValue(defaultFieldValue,moduleBean);
		//是否包含所有非空字段
		message += this.HasAllNotNullFieldInRest(fieldsSet, fieldsNames.toString());
		
		SimpleVO simple = new SimpleVO();
		String id = null;
		if(baseVO != null)
		{
			id = baseVO.getId();
		}
		simple.setModule(moduleBean);
		simple.setTableName(moduleBean.getDbTable());
		simple.getDetail().putAll(defaultDetail);
		String content =null;
		int j=0;
		for(String key : details.keySet())
		{
			content=null;
			if("access_token".equals(key)||key.contains("-ori"))
				continue;
			MdFieldEntity field = fields.get(j);
			content = details.get(key)[0].trim();
			
			if(ModuleConstants.COMMON_NO.equals(field.getNullable()) && StringUtils.isBlank(content)){
				error.append(field.getEntityName()+"不能为空");
				throw new Exception(error.toString());
			}
			if(StringUtils.isNotBlank(content)){
				if(dic.containsKey(field.getEntityName())){
					FieldVO vo = dic.get(field.getEntityName());
					if(vo.getText()!=null){
						simple.addDetail(vo.getText(), content.trim());
					}
					String value = vo.getValue(content);
					if(StringUtils.isBlank(value)){
						error.append(field.getForm().getEntityName()+"的数据在系统内不存在，已设为空值");
						throw new Exception(error.toString());
					}
					else{
						simple.addDetail(vo.getId(), value.trim());
					}
				}else if(StringUtils.isNotBlank(field.getForm().getDataBean())){
					Class<?> c = Class.forName(field.getForm().getDataBean());
					DataSelector bean = (DataSelector)c.newInstance();
					JSONObject obj = bean.getData(content);
					simple.addDetail(field, content);
					for(MdFieldEntity f : fieldsSet){
						if(obj.containsKey(f.getFieldName())){
							simple.addDetail(f, obj.get(f.getFieldName()));
						}
					}
				}else{
					try {
						if(convert(type,field.getDisplayType(),content) != null)
						{
							simple.addDetail(field, convert(type,field.getDisplayType(),content));
						}
						else{
							error.append(field.getForm().getDisplayName()+"请输入正确的类型"+field.getDisplayType());
							throw new Exception(error.toString());
						}
					} catch (NumberFormatException e) {
						error.append(field.getForm().getDisplayName()+"不是数字");
						throw new Exception(error.toString());
					} catch (DateParseException e) {
						error.append(field.getForm().getDisplayName()+"不是日期");	
						throw new Exception(error.toString());
					}
				}
			}else{
				simple.addDetail(field, null);
			}
			if(StringUtils.isBlank(simple.getId())){
				if(simple.getUniqueMap()!=null&&simple.getUniqueMap().size()>0){
					baseDAO.initModule(simple.getModule());
					id = getByUnique(simple.getUniqueMap());
				}
			}else{
				id = simple.getId();
			}
			if(StringUtils.isNotBlank(id)){
				simple.setId(id);
				simple.getDetail().put("id", id);
				simple.initLinks();
				if (moduleBase != null) {
					if(!moduleBase.canUpdate(simple)){
						error.append(field.getForm().getDisplayName()+"该表单已提交,不允许修改!");	
						throw new Exception(error.toString());
					}
				}
				
			}else{
				simple.initLinks();
				simple.initFields();
				for(String key2 : defaultFields.keySet()){
					simple.getDetail().put(key2, defaultFields.get(key));
				}
			}
			j++;
		}
		if(StringUtils.isNotBlank(error.toString()))
		{
			throw new Exception(error.toString());
		}
		if(StringUtils.isNotBlank(id))
		{
			baseDAO.update(simple);
		}
		else
		{
			id = UUIDUtils.uuid32();
			simple.setId(id);
			simple.getDetail().put("id", id);
			baseDAO.create(simple);
		}
		BaseVO vo = new BaseVO(moduleBean);
		vo.setId(id);
		if(baseVO == null){
			baseVO = new BaseVO();
		}
		baseVO.getDetailMap().putAll(simple.getDetail());
		vo.setDetailMap(baseVO.getDetailMap());
		return vo;
	}
	
	/**
	 * 导入的字段集是否包含所有非空字段
	 * @param baseDetails 实体类下所有字段集
	 * @param details 导入标题栏对应字段集
	 * @return
	 * @throws ExcelImportException 
	 */
	
	public String HasAllNotNullFieldInRest(Set<MdFieldEntity> baseFields,String fieldsName) throws ExcelImportException{
		String message = "";
		for(MdFieldEntity baseField : baseFields){
			//跳过主键
			if("id".equals(baseField.getForm().getEntityName().toLowerCase())){
				continue;
			}
			//该字段为必填字段
			if(baseField.getNullable()!= 1 && baseField.getDefaultValue()==null){
				//导入的字段集不包含非空字段
				if(!fieldsName.contains(baseField.getEntityName())){
					message+=baseField.getForm().getEntityName()+"不可为空";
				}
			}
		}
		return message;
	} 
	
	/*
	 * 获取列名对应的字段集
	 * 判断标题字段是否存在数据库表结构中
	 */
	public Map<Integer, MdFieldEntity> getDetailInRest(Map<String, MdFieldEntity> map,Map<Integer,String> displayNames) throws ExcelImportException{
		if(displayNames.size() >0){
			Map<Integer, MdFieldEntity> field = new HashMap<Integer, MdFieldEntity>();
			int i=0;
			for(Integer key : displayNames.keySet()){
				String displayName = displayNames.get(key);
				if("access_token".equals(displayName))
					continue;
				if(map.containsKey(displayName)){
					field.put(i,map.get(displayName));
				}else{
					throw new ExcelImportException("数据库中没有字段：'"+displayName+"'");
				}
				i++;
			}
			return field;
		}
		return null;
	}
	
	protected Map<String, MdFieldEntity> genByModuleInRest(Set<MdFieldEntity> fields, Map<String, FieldVO> dic) throws Exception{
		Map<String, MdFieldEntity> map = new HashMap<String, MdFieldEntity>();
		
		for(MdFieldEntity field : fields){
			map.put(field.getForm().getEntityName(), field);
			if(field.getForm().getDataSource()!=null){
				FieldVO vo = new FieldVO();
				if(StringUtils.isNotBlank(field.getForm().getValueFieldID())){
					if(field.getEntityName().equals(field.getForm().getValueFieldID())){
						vo.setId(field);
					}else {
						for(MdFieldEntity f : fields){
							if(f.getEntityName().equals(field.getForm().getValueFieldID())){
								vo.setId(f);
							}
						}
					}
				}else{
					vo.setId(field);
				}
				if(field.getEntityName().equals(field.getForm().getValueFieldText())){
					vo.setText(field);
				}else {
					for(MdFieldEntity f : fields){
						if(f.getEntityName().equals(field.getForm().getValueFieldText())){
							vo.setText(f);
						}
					}
				}
				if(ModuleConstants.DATA_SOURCE_DIC.equals(field.getForm().getDataSource())){
					vo.setDetails(DictionaryLib.getDictionarySelectByCode(field.getForm().getDicName()));
				}else if(ModuleConstants.DATA_SOURCE_CUSTOM.equals(field.getForm().getDataSource()) && StringUtils.isNotBlank(field.getForm().getDataBean())){
					try {
						Class<?> c = Class.forName(field.getForm().getDataBean());
						DataBeanSelector bean = (DataBeanSelector)c.newInstance();
						vo.setDetails(bean.getSelector());
					} catch (ClassCastException e) {
					} catch (Exception e) {
						logger.error(e);
					}
				}
				if(!vo.getDetails().isEmpty()){
					dic.put(field.getEntityName(), vo);
				}
			}
		}
		return map;
	}

}
